package npr;

import javax.media.opengl.*;

import processing.core.PApplet;

/**
 * This class is the superclass for algorithms and provides the necessary infrastructure. */
public class Algorithm{

    /** The algorithm's start index in the matrix history. Is set by the renderer when the algorithm calls begin(). */
    protected int start;
    /** The algorithm's start index in the matrix history. Is set by the renderer when the algorithm calls end(). */
    protected int stop;
    /** a handle to the renderer to call it's methods. Always call renderer= (NPR)parent.g; before using this variable, as the renderer may change. */
    protected NPR renderer;
    /** The parent applet. Gets set by the renderer automatically.*/
    protected static PApplet parent;
    /** a handle to the Renderer's gl object. Always call gl= renderer.gl; before using this variable */
    protected GL gl;


    /**
     * Creates an Algorithm object. Algorithm is not to be instantiated directly, only its various subclasses.
     */
    public Algorithm(){
    }

    /**
     * Sets the parent applet. This is called by the renderer automatically.
     */ 
    protected static void setParent(PApplet applet){
      
	parent= applet;
    }


    /**
     * Starts using this algorithm. Registers an algorithm with the renderer. 
     * The first call to begin() puts the renderer in NPR mode, which means you can't use hint(ENABLE_DEPTH_SORT)
     * and you have to use NPR lighting. Processing lighting is disabled.
     */
    public void begin(){
	renderer= (NPR)parent.g; 
	renderer.begin(this); 
    }


    /**
     * Ends using this algorithm. Deregisters an algorithm with the renderer. The last algorithm calling end() ends NPR mode. 
     */
    public void end(){
	renderer= (NPR)parent.g;
	renderer.end(this);
    }


    /**
     * Callback for developing custom algorithms. Everything in here should be rendered to a texture.
     */
    public void preProcess(){}

    /**
     * Callback for developing custom algorithms. Everything in here is rendered to the screen
     */    
    public void postProcess(){}


    /**
     * Callback for developing custom algorithms. Sets the state of the main shader. You need to implement this only
     * when developing new shading or shadow algorithms.
     */
    protected void prepare(){}

    
    /**
     * Callback for developing custom algorithms. Resets any OpenGL state that may have been set in prepare(). You need to implement this only
     * when developing new shading or shadow algorithms.
     */
   protected void cleanUp(){}


    /**
     * Renders the algorithm's segment of the matrix history by pushing the appropriate modelview matrices on the matrix stack.
     * If you need other matrices going to other targets, like textures, use the renderer's method
     * render(int start, int stop, int[] modelviewTargets, int[] modelTargets, int[] cameraTargets, int[] cameraInvTargets)
     */
    protected void render(){
	renderer= (NPR)parent.g;
	renderer.render(start, stop);
    }
    
}
